<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>

<body>

<!--

1.app.message修改数据，Vue内部是如何监听message数据的改变
* Object.defineProperty -> 监听对象属性的改变

2.当数据发生改变，Vue是如何知道要通知哪些数据，使之界面发生刷新
* 发布订阅者模式

-->

<div id="app">
  {{message}}
  {{message}}
  {{message}}
</div>

<script>
  const obj = {
    message: '哈哈哈',
    name: 'why'
  }

  Object.keys(obj).forEach(key => {
    let value = obj[key];

    Object.defineProperty(obj, key, {
      set(newValue) {
        console.log('监听' + key + '改变');
        // 根据解析html代码，获取到哪些人在用属性
        value = newValue;
      },
      get() {
        console.log('获取' + key + '对应的值');
        return value;
      }
    })
  })

  // 发布订阅者模式
  // 发布者
  class Dep {
    constructor() {
      this.subs = []
    }

    addSub(watcher) {
      this.subs.push(watcher)
    }

    notify() {
      this.subs.forEach(item => {
        item.update()
      })
    }
  }

  // 订阅者
  class Watcher {
    constructor(name) {
      this.name = name;
    }

    update() {
      console.log(this.name + '发生update');
    }
  }

  const dep = new Dep();

  const w1 = new Watcher('张三');
  dep.addSub(w1);

  const w2 = new Watcher('李四');
  dep.addSub(w2);

  const w3 = new Watcher('王五');
  dep.addSub(w3);
</script>
<script src="./node_modules/vue/dist/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      message: '哈哈哈',
      name: 'why'
    }
  })
</script>

</body>

</html>
